iT邦幫忙

2023 iThome 鐵人賽

DAY 7
0
自我挑戰組

設計模式系列 第 7

Day7 - 建造模式(Builder pattern)

  • 分享至 

  • xImage
  •  

介紹
建造模式將複雜物件的建造過程抽象出來,該抽象可被不同創建細節的物件所實作。

以海綿寶寶卡通為例,海綿寶寶製作蟹堡是將食材從下往上堆疊,每層使用的食材是根據蟹老闆的祖傳祕方。這裡的從下往上堆疊可看作是"建造過程",每層使用的食材則是"物件實作的細節"。假如哪天蟹老闆改變了秘方內容,海綿寶寶製作漢堡的"建造過程"依舊是從下往上堆疊,但使用的食材則會改變,結果就是新的美味蟹堡誕生。

C++範例

#include <iostream>
#include <string>
#include <memory>

// 漢堡製作方式
class Hamburger
{
public:
    // 漢堡製作方式是從底層往上堆疊食材,這裡把漢堡製作分底、中、上層
    void SetBottomIngredient(const std::string &bottom)
    {
        m_bottom = bottom;
    }

    void SetMiddleIngredient(const std::string &middle)
    {
        m_middle = middle;
    }

    void SetTopIngredient(const std::string &top)
    {
        m_top = top;
    }

    void Show() const
    {
        std::cout << "Hamburger with" << std::endl
                  << "bottom:" << m_bottom << std::endl
                  << "middle:" << m_middle << std::endl
                  << "top:" << m_top << std::endl;
    }

private:
    std::string m_bottom;
    std::string m_middle;
    std::string m_top;
};

// 抽象漢堡建造
class HamburgerBuilder
{
public:
    virtual ~HamburgerBuilder() {}

    Hamburger *GetHamburger()
    {
        return m_Hamburger.get();
    }

    void CreateNewHamburgerProduct()
    {
        m_Hamburger = std::make_unique<Hamburger>();
    }

    virtual void BuildBottom() = 0;
    virtual void BuildMiddle() = 0;
    virtual void BuildTop() = 0;

protected:
    std::unique_ptr<Hamburger> m_Hamburger;
};

// 蟹老闆漢堡實作
class KrabsHamburgerBuilder : public HamburgerBuilder
{
public:
    virtual void BuildBottom() override
    {
        m_Hamburger->SetBottomIngredient("whole wheat bread");
    }

    virtual void BuildMiddle() override
    {
        m_Hamburger->SetMiddleIngredient("lettuce, crisp onions, tomatoes, sea cheese");
    }

    virtual void BuildTop() override
    {
        m_Hamburger->SetTopIngredient("whole wheat bread");
    }
};

// 皮老闆漢堡實作
class PlanktonHamburgerBuilder : public HamburgerBuilder
{
public:
    virtual void BuildBottom() override
    {
        m_Hamburger->SetBottomIngredient("radioactive bread");
    }

    virtual void BuildMiddle() override
    {
        m_Hamburger->SetMiddleIngredient("boots, socks, metal");
    }

    virtual void BuildTop() override
    {
        m_Hamburger->SetTopIngredient("radioactive bread");
    }
};

// 廚師-海綿寶寶
class SpongebobTheCook
{
public:
    void ShowHamburger()
    {
        m_HamburgerBuilder->GetHamburger()->Show();
    }
    void MakeHamburger(HamburgerBuilder *hb)
    {
        m_HamburgerBuilder = hb;

        // 漢堡從下往上堆疊食材
        m_HamburgerBuilder->CreateNewHamburgerProduct();
        m_HamburgerBuilder->BuildBottom();
        m_HamburgerBuilder->BuildMiddle();
        m_HamburgerBuilder->BuildTop();
    }

private:
    HamburgerBuilder *m_HamburgerBuilder;
};

int main()
{
    // 創建海綿寶寶廚師
    SpongebobTheCook spongebob;

    // 創建蟹老闆及皮老闆漢堡的製作方法
    KrabsHamburgerBuilder krabsHamburgerBuilder;
    PlanktonHamburgerBuilder planktonHamburgerBuilder;

    // 製作蟹老闆漢堡
    spongebob.MakeHamburger(&krabsHamburgerBuilder);
    spongebob.ShowHamburger();
    // 製作皮老闆漢堡
    spongebob.MakeHamburger(&planktonHamburgerBuilder);
    spongebob.ShowHamburger();

    return 0;
}

Output:

Hamburger with
bottom:whole wheat bread
middle:lettuce, crisp onions, tomatoes, sea cheese
top:whole wheat bread
Hamburger with
bottom:radioactive bread
middle:boots, socks, metal
top:radioactive bread

Ref:
https://en.wikibooks.org/wiki/C%2B%2B_Programming/Code/Design_Patterns#Builder


上一篇
Day6 - 工廠模式: 抽象工廠模式(Abstract factory pattern)
下一篇
Day8 - 適配器模式(Adapter pattern)
系列文
設計模式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言